package org.akomantoso.core.io.util.torefactor;

import java.io.IOException;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import org.akomantoso.core.data.Content;
import org.akomantoso.core.data.Paragraph;
import org.akomantoso.core.data.PopupStructureElement;
import org.akomantoso.core.data.Recital;
import org.akomantoso.core.io.Input;
import org.akomantoso.core.io.InputConstants;
import org.akomantoso.core.io.util.Instantiator;
import org.akomantoso.core.io.util.group.BlockElementsGroup;
import org.akomantoso.core.io.util.group.HierElementsGroup;
import org.akomantoso.core.util.MapUtil;

/**
 * @author <a href="mailto:jacques.militello@gmail.com">Jacques Militello</a>
 */
public final class PopupStructureElementUtil {

	private PopupStructureElementUtil() {
	}

	static final Map<String, Instantiator<PopupStructureElement>> ITEMS = new IdentityHashMap<String, Instantiator<PopupStructureElement>>();

	public static void read(Input in, List<PopupStructureElement> elements) throws IOException {

		PopupStructureElement element = null;
		final String localName = in.getLocalName();

		while (true) {
			in.readNext();
			switch (in.getEventType()) {
			case InputConstants.START_ELEMENT:
				elements.add(element = instantiate(in.getLocalName()));
				element.readExternal(in);
				break;
			case InputConstants.END_ELEMENT:
				if (localName == in.getLocalName()) {
					return;
				}
			}
		}
	}

	static PopupStructureElement instantiate(String elementName) {

		final Instantiator<PopupStructureElement> instatiator = ITEMS.get(elementName);
		if (instatiator == null) {
			throw new RuntimeException("Tag [" + elementName + "] not supported for PopupStructureElement ?!?");
		}
		return instatiator.instantiate();

	}

	static {

		// recital
		ITEMS.put(Recital.ELEMENT.intern(), new Instantiator<PopupStructureElement>() {
			public Recital instantiate() {
				return new Recital();
			}
		});
		
		ITEMS.put(Paragraph.ELEMENT.intern(), new Instantiator<PopupStructureElement>() {
			public Paragraph instantiate() {
				return new Paragraph();
			}
		});

		// content
		ITEMS.put(Content.ELEMENT.intern(), new Instantiator<PopupStructureElement>() {
			public Content instantiate() {
				return new Content();
			}
		});

		MapUtil.copy(BlockElementsGroup.MAP, ITEMS);
		MapUtil.copy(HierElementsGroup.MAP, ITEMS);
	}

}